package com.av.client.frames;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;

import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.error.ErrorInfo;

import com.av.client.components.AvButton;
import com.av.client.components.AvComponent;
import com.av.client.components.AvLabel;
import com.av.client.util.idioma.Error;
import com.av.client.util.idioma.Etiqueta;
import com.av.client.util.idioma.ManejadorIdiomas;
import com.av.client.util.idioma.ManejadorIdiomas.IdiomaEvent;
import com.av.client.util.idioma.ManejadorIdiomas.IdiomaEventListener;
import com.av.client.util.sesion.AdministradorSesion;
import com.av.db.dataobjects.Tarjeta;
import com.av.db.dataobjects.Usuario;
import com.av.db.dataobjects.enums.Rol;
import com.av.exceptions.AvDBException;
import com.av.exceptions.AvException;
import com.av.rmi.CatalogoAcciones;
import com.av.rmi.Parametro;
import com.av.rmi.Parametro.Tipo;

/**
 * Clase creada para permitir al usuario la administracion de las tarjetas
 * 
 * @author J Francisco Ruvalcaba C
 * 
 */
@SuppressWarnings("serial")
public class TarjetaFrame extends JInternalFrame {

	private static final int WIDTH = 750;
	private static final int HEIGHT = 300;

	private AvLabel lblTarjetaCodigo;
	private JTextField txtTarjetaCodigo;
	private AvLabel lblTarjetaNumPlaca;
	private JTextField txtTarjetaNumPlaca;
	private JCheckBox chkActivo;
	private AvLabel lblUsuarios;
	private JComboBox cboUsuarios;
	private JTable tblTarjetas;
	private AvButton btnAgregar;
	private AvButton btnActualizar;
	private AvButton btnEliminar;
	private AvButton btnCerrar;

	private TarjetaModel tm;
	private ManejadorIdiomas mi;
	private BotonHandler bh = new BotonHandler();
	private Tarjeta tarjetaSeleccionada;
	private Tarjeta[] tarjetas;
	private Usuario[] usuariosActivos;

	public TarjetaFrame() {
		super();
		mi = ManejadorIdiomas.getInstance();
		initComponents();
		addListeners();
		cargarPermisos();
		cargarTarjetas();
		limpiarTextos();
	}// TarjetaFrame

	/**
	 * Funcion que habilita o deshabilita los componentes de acuerdo a sus
	 * permisos asignados
	 */
	private void cargarPermisos() {
		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			Rol r = AdministradorSesion.getInstance().getSesionActiva()
					.getUsuario().getRol();
			for (Component c : this.getContentPane().getComponents()) {
				if (c instanceof JPanel) {
					for (Component c2 : ((JPanel) c).getComponents()) {
						if (c2 instanceof AvComponent) {
							c2.setEnabled(((AvComponent) c2).contains(r));
						}
					}
				} else if (c instanceof AvComponent) {
					c.setEnabled(((AvComponent) c).contains(r));
				}
			}
		}
	}// cargarPermisos

	private void addListeners() {
		mi.addIdiomaEventListener(new IdiomaEventListener() {
			@Override
			public void changedIdiomaEvent(IdiomaEvent evt) {
				setLabels();
			}
		});

		tblTarjetas.getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {
					@Override
					public void valueChanged(ListSelectionEvent e) {
						if (tarjetas != null
								&& tblTarjetas.getSelectedRow() >= 0
								&& tblTarjetas.getSelectedRow() < tarjetas.length) {
							setTarjeta(tarjetas[tblTarjetas.getSelectedRow()]);
						}
					}
				});

		btnAgregar.addActionListener(bh);
		btnEliminar.addActionListener(bh);
		btnActualizar.addActionListener(bh);
		btnCerrar.addActionListener(bh);
	}// addListeners

	/**
	 * Funcion que restablece las etiquetas para todos los componentes
	 */
	private void setLabels() {
		setTitle(mi.obtenerEtiqueta(Etiqueta.TARJETA_FRAME_TITLE));
		lblTarjetaCodigo.setText(Etiqueta.TARJETA_FRAME_LBL_TARJETACODIGO);
		lblTarjetaNumPlaca.setText(Etiqueta.TARJETA_FRAME_LBL_TARJETANUMPLACA);
		chkActivo
				.setText(mi.obtenerEtiqueta(Etiqueta.TARJETA_FRAME_CHK_ACTIVO));
		lblUsuarios.setText(Etiqueta.TARJETA_FRAME_LBL_USUARIOS);
		btnActualizar.setText(Etiqueta.TARJETA_FRAME_BTN_ACTUALIZAR);
		btnEliminar.setText(Etiqueta.TARJETA_FRAME_BTN_ELIMINAR);
		btnAgregar.setText(Etiqueta.TARJETA_FRAME_BTN_AGREGAR);
		btnCerrar.setText(Etiqueta.TARJETA_FRAME_BTN_CERRAR);
		String[] headers = (mi
				.obtenerEtiqueta(Etiqueta.TARJETA_FRAME_TBL_USUARIOS_COLUMN_NAMES))
				.split(",");
		if (headers != null && tblTarjetas.getColumnCount() == headers.length) {
			for (int i = 0; i < tblTarjetas.getColumnCount(); i++) {
				tblTarjetas.getColumnModel().getColumn(i).setHeaderValue(
						headers[i]);
			}
		}
	}// setLabels

	/**
	 * Funcion que configura todos los componentes y su correcta colocacion
	 */
	private void initComponents() {
		setTitle(mi.obtenerEtiqueta(Etiqueta.TARJETA_FRAME_TITLE));
		setLayout(new GridBagLayout());
		GridBagConstraints gc = new GridBagConstraints();

		gc.insets = new Insets(5, 5, 5, 5);
		gc.fill = GridBagConstraints.HORIZONTAL;

		// TarjetaCodigo
		gc.gridx = 0;
		lblTarjetaCodigo = new AvLabel(Etiqueta.TARJETA_FRAME_LBL_TARJETACODIGO);
		add(lblTarjetaCodigo, gc);

		gc.gridx = 1;
		gc.weightx = 1.0;
		txtTarjetaCodigo = new JTextField();
		add(txtTarjetaCodigo, gc);
		gc.weightx = 0.0;

		// TarjetaNumPlaca
		gc.gridx = 2;
		lblTarjetaNumPlaca = new AvLabel(
				Etiqueta.TARJETA_FRAME_LBL_TARJETANUMPLACA);
		add(lblTarjetaNumPlaca, gc);

		gc.gridx = 3;
		gc.weightx = 1.0;
		txtTarjetaNumPlaca = new JTextField();
		add(txtTarjetaNumPlaca, gc);
		gc.weightx = 0.0;

		// Usuarios
		gc.gridy = 1;
		gc.gridx = 0;
		lblUsuarios = new AvLabel(Etiqueta.TARJETA_FRAME_LBL_USUARIOS);
		add(lblUsuarios, gc);

		gc.gridx = 1;
		usuariosActivos = obtenerUsuariosActivos();
		cboUsuarios = new JComboBox(usuariosActivos);
		add(cboUsuarios, gc);

		// Activo
		gc.gridx = 2;
		gc.gridwidth = 2;
		chkActivo = new JCheckBox(mi
				.obtenerEtiqueta(Etiqueta.TARJETA_FRAME_CHK_ACTIVO));
		add(chkActivo, gc);
		gc.gridwidth = 1;

		// Botones
		JPanel jpnl = new JPanel(new FlowLayout());

		btnAgregar = new AvButton(Etiqueta.TARJETA_FRAME_BTN_AGREGAR);
		btnAgregar.addPermiso(Rol.ADMIN);
		jpnl.add(btnAgregar);

		btnEliminar = new AvButton(Etiqueta.TARJETA_FRAME_BTN_ELIMINAR);
		btnEliminar.addPermiso(Rol.ADMIN);
		jpnl.add(btnEliminar);

		btnActualizar = new AvButton(Etiqueta.TARJETA_FRAME_BTN_ACTUALIZAR);
		btnActualizar.addPermiso(Rol.ADMIN);
		jpnl.add(btnActualizar);

		btnCerrar = new AvButton(Etiqueta.TARJETA_FRAME_BTN_CERRAR);
		btnCerrar.loadPermisos();
		jpnl.add(btnCerrar);

		gc.gridy = 2;
		gc.gridx = 0;
		gc.gridwidth = 4;
		gc.weightx = 1.0;
		add(jpnl, gc);
		gc.gridwidth = 1;
		gc.weightx = 0.0;

		// Tabla de resultados

		gc.gridy = 3;
		gc.gridwidth = 4;
		gc.weightx = 1.0;
		gc.weighty = 1.0;
		gc.fill = GridBagConstraints.BOTH;
		tm = new TarjetaModel(0);
		tblTarjetas = new JTable(tm);
		tblTarjetas
				.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		add(new JScrollPane(tblTarjetas), gc);

		setClosable(false);
		setSize(WIDTH, HEIGHT);
	}// initComponents

	/**
	 * Funcion que obtiene los usuarios activos registrados en el sistema
	 * 
	 * @return
	 */
	private Usuario[] obtenerUsuariosActivos() {
		Usuario[] tmp = new Usuario[1];
		Parametro p = new Parametro();

		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			try {
				p.setAccion(CatalogoAcciones.OBTENER_ACTIVOS_USUARIO);
				p = AdministradorSesion.getInstance().getSesionActiva()
						.ejecutar(p);
				if (p.getValor(Tipo.OUTPUT) != null) {
					tmp = (Usuario[]) p.getValor(Tipo.OUTPUT);
				}
			} catch (AvException e) {
				ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR", e
						.getMessage(), null, null, e, Level.INFO, null);
				JXErrorPane.setDefaultLocale(mi.getIdioma().getLocale());
				JXErrorPane.showDialog(getParent(), info);
			}
		}

		return tmp;
	}// obtenerUsuariosActivos

	private class TarjetaModel extends AbstractTableModel {
		private Map<Point, Object> lookup;
		private final int rows;
		private final int columns;
		private final String headers[];

		public TarjetaModel(int rows) {
			this.rows = rows;
			this.headers = mi.obtenerEtiqueta(
					Etiqueta.TARJETA_FRAME_TBL_USUARIOS_COLUMN_NAMES)
					.split(",");
			this.columns = headers.length;

			lookup = new HashMap<Point, Object>();
		}

		public int getColumnCount() {
			return columns;
		}

		public int getRowCount() {
			return rows;
		}

		public String getColumnName(int column) {
			return headers[column];
		}

		public Object getValueAt(int row, int column) {
			return lookup.get(new Point(row, column));
		}

		public void setValueAt(Object value, int row, int column) {
			if ((rows < 0) || (columns < 0)) {
				throw new IllegalArgumentException("Invalid row/column setting");
			}
			if ((row < rows) && (column < columns)) {
				lookup.put(new Point(row, column), value);
			}
		}
	}

	/**
	 * Funcion que valida que los campos requeridos del formulario
	 * 
	 * @throws AvDBException
	 */
	private void validarTextos() throws AvException {
		if (txtTarjetaCodigo.getText() == null
				|| txtTarjetaCodigo.getText().trim().length() == 0) {
			txtTarjetaCodigo.requestFocus();
			throw new AvException(mi
					.obtenerError(Error.TARJETA_FRAME_TXT_CODIGO));
		}
		if (txtTarjetaNumPlaca.getText() == null
				|| txtTarjetaNumPlaca.getText().trim().length() == 0) {
			txtTarjetaNumPlaca.requestFocus();
			throw new AvException(mi
					.obtenerError(Error.TARJETA_FRAME_TXT_NUMPLACA));
		}
		if (cboUsuarios.getSelectedIndex() < 0) {
			cboUsuarios.requestFocus();
			throw new AvException(mi
					.obtenerError(Error.tARJETA_FRAME_CBO_USUARIOS));
		}
	}// validarTextos

	private Tarjeta getTarjeta() {
		if (tarjetaSeleccionada == null) {
			tarjetaSeleccionada = new Tarjeta();
		}

		tarjetaSeleccionada.setActivo(chkActivo.isSelected());
		tarjetaSeleccionada.setCodigo(txtTarjetaCodigo.getText());
		tarjetaSeleccionada.setNumPlaca(txtTarjetaNumPlaca.getText());
		tarjetaSeleccionada.setUsuario((Usuario) cboUsuarios.getSelectedItem());

		return tarjetaSeleccionada;
	}// getTarjeta

	private void setTarjeta(Tarjeta t) {
		if (t != null) {
			tarjetaSeleccionada = t;

			chkActivo.setSelected(t.isActivo());
			txtTarjetaNumPlaca.setText(t.getNumPlaca());
			txtTarjetaCodigo.setText(t.getCodigo());
			cboUsuarios.setSelectedItem(t.getUsuario());

		}
	}// setTarjeta

	private void limpiarTextos() {
		cboUsuarios.setSelectedIndex(-1);
		chkActivo.setSelected(false);
		txtTarjetaNumPlaca.setText("");
		txtTarjetaCodigo.setText("");
	}// limpiarTextos

	/**
	 * Clase creada para la administracion de acciones
	 * 
	 * @author J Francisco Ruvalcaba C
	 * 
	 */
	private class BotonHandler implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent ev) {
			Object o = ev.getSource();
			if (o instanceof AvButton) {
				if (o == btnCerrar) {
					dispose();
				} else if (o == btnActualizar) {
					try {
						validarTextos();
						actualizarTarjeta();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}

				} else if (o == btnEliminar) {
					try {
						validarTextos();
						eliminarTarjeta();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}
				} else if (o == btnAgregar) {
					try {
						validarTextos();
						agregarTarjeta();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}
				}
			}
		}// actionPerformed
	}// BotonHandler

	/**
	 * Funcion que agrega una tarjeta a partir de los datos capturados
	 * 
	 * @throws AvException
	 */
	private void agregarTarjeta() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.AGREGAR_TARJETA);
		tarjetaSeleccionada = new Tarjeta();
		p.setValor(Tipo.INPUT, getTarjeta());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarTarjetas();
	}// agregarTarjeta

	/**
	 * Funcion que actualiza una tarjeta con los datos capturados
	 * 
	 * @throws AvException
	 */
	private void actualizarTarjeta() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.ACTUALIZAR_TARJETA);
		p.setValor(Tipo.INPUT, getTarjeta());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarTarjetas();
	}// actualizarTarjeta

	/**
	 * Funcion que elimina la tarjeta seleccionada
	 * 
	 * @throws AvException
	 */
	private void eliminarTarjeta() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.ELIMINAR_TARJETA);
		p.setValor(Tipo.INPUT, getTarjeta());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarTarjetas();
	}// actualizarTarjeta

	/**
	 * Funcion que carga en la tabla todas las tarjetas registradas en el
	 * sistema
	 */
	private void cargarTarjetas() {
		Parametro p = new Parametro();
		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			try {
				p.setAccion(CatalogoAcciones.OBTENER_TODOS_TARJETA);
				p = AdministradorSesion.getInstance().getSesionActiva()
						.ejecutar(p);
				if (p.getValor(Tipo.OUTPUT) != null) {
					tarjetas = (Tarjeta[]) p.getValor(Tipo.OUTPUT);
					tm = new TarjetaModel(tarjetas.length);
					int row = 0;
					for (Tarjeta t : tarjetas) {
						tm.setValueAt(t.getCodigo(), row, 0);
						tm.setValueAt(t.getNumPlaca(), row, 1);
						tm.setValueAt(t.isActivo(), row, 2);
						tm.setValueAt(t.getUsuario(), row, 3);
						row++;
					}
					tblTarjetas.setModel(tm);
				}
			} catch (AvException e) {
				ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR", e
						.getMessage(), null, null, e, Level.INFO, null);
				JXErrorPane.setDefaultLocale(mi.getIdioma().getLocale());
				JXErrorPane.showDialog(getParent(), info);
			}
		}
	}// cargarTarjetas

	public static void main(String[] args) {
		JFrame tmp = new JFrame("Test");
		tmp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JDesktopPane desktop = new JDesktopPane();
		desktop.setBackground(Color.GRAY);
		desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
		tmp.setContentPane(desktop);

		TarjetaFrame ea = new TarjetaFrame();
		ea.setVisible(true);
		desktop.add(ea);
		try {
			ea.setSelected(true);
		} catch (PropertyVetoException e) {
		}
		tmp.setSize(new Dimension(ea.getWidth() + 100, ea.getHeight() + 100));
		tmp.setVisible(true);
	}// main

}// TarjetaFrame